package main

import (
	"errors"
	"fmt"
)

//错误是最后一个返回值，并且具有类型error，一个内置的接口
//errors.Newerror用给定的错误信息构造一个基本值
func f1(arg int) (int, error) {
	if arg == 42 {
		return -1, errors.New("can't work with 42")
	}
	return arg + 3, nil
}

type argError struct {
	arg  int
	prob string
}

func (e *argError) Error() string {
	return fmt.Sprintf("%d - %s", e.arg, e.prob)
}

func f2(arg int) (int, error) {
	if arg == 42 {
		return -1, &argError{arg, "can't work with it"}
	}
	return arg + 3, nil
}

func main() {
	for _, i := range []int{2, 42} {
		if r, e := f1(i); e != nil {
			fmt.Println("f1 failed:", e)
		} else {
			fmt.Println("f1 worked:", r)
		}

	}

	for _, i := range []int{2, 42} {
		if r, e := f2(i); e != nil {
			fmt.Println("f2 failed:", e)
		} else {
			fmt.Println("f2 worked:", r)
		}

	}

	//如果要以编程方式在自定义错误中使用数据，则需要通过类型断言将错误作为自定义错误类型的实例
	_, e := f2(42)
	if ae, ok := e.(*argError); ok {
		fmt.Println(ae)
		fmt.Println(ok)
		fmt.Println(ae.arg)
		fmt.Println(ae.prob)
	}
}
